// ChatClientLobbyDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Chat.h"
#include "ChatClientLobbyDlg.h"
#include "ChatClientDoc.h"
#include "ChatRoomClientDlg.h"

// CChatClientLobbyDlg dialog

IMPLEMENT_DYNAMIC(CChatClientLobbyDlg, CDialog)

CChatClientLobbyDlg::CChatClientLobbyDlg(CWnd* pParent /*=NULL*/)
	: CChatClientBaseDlg(CChatClientLobbyDlg::IDD, pParent)
	, m_port(CHATLOBBY_SERVER_PORT)
	, m_coordinatorPort(CHATSERVER_COORDINATOR_PORT)
{

}

CChatClientLobbyDlg::~CChatClientLobbyDlg()
{
	for(int i = 0; i < m_lobby.GetItemCount(); ++i)
	{
		delete reinterpret_cast<NetworkID*>(m_lobby.GetItemData(i));
		m_lobby.SetItemData(i, NULL);
	}
}

void CChatClientLobbyDlg::DoDataExchange(CDataExchange* pDX)
{
	CChatClientBaseDlg::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_IPADDRESS_CHATCLIENT, m_ipAddress);
	DDX_Text(pDX, IDC_EDIT_PORT, m_port);
	DDV_MinMaxUInt(pDX, m_port, 0, 65535);
	DDX_Control(pDX, IDC_LIST_LOBBY, m_lobby);
	DDX_Control(pDX, IDC_IPADDRESS_CHATSERVER_COORDINATOR, m_coordinatorAddress);
	DDX_Text(pDX, IDC_EDIT_PORT_COORDINATOR, m_coordinatorPort);
}


BEGIN_MESSAGE_MAP(CChatClientLobbyDlg, CDialog)
	ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CChatClientLobbyDlg::OnBnClickedButtonConnect)
	ON_BN_CLICKED(IDC_BUTTON_CREATE_ROOM, &CChatClientLobbyDlg::OnBnClickedButtonCreateRoom)
	ON_BN_CLICKED(IDC_BUTTON_JOIN_ROOM, &CChatClientLobbyDlg::OnBnClickedButtonJoinRoom)
END_MESSAGE_MAP()


// CChatClientLobbyDlg message handlers

void CChatClientLobbyDlg::OnBnClickedButtonConnect()
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);

	BYTE ipByte[4];
	m_ipAddress.GetAddress(ipByte[0], ipByte[1], ipByte[2], ipByte[3]);

	CStringA strAddress;
	strAddress.Format(("%d.%d.%d.%d"), ipByte[0], ipByte[1], ipByte[2], ipByte[3]);

	GetChatClientDoc().Connect(strAddress.GetBuffer(), m_port);
}

BOOL CChatClientLobbyDlg::OnInitDialog()
{
	CChatClientBaseDlg::OnInitDialog();

	// TODO:  Add extra initialization here
	m_lobby.InsertColumn(0, _T("ID"), LVCFMT_LEFT, 100);
	m_lobby.InsertColumn(1, _T("Name"), LVCFMT_LEFT, 300);

	m_ipAddress.SetAddress(SERVER_ADDRESS);
	m_coordinatorAddress.SetAddress(COORDIANTOR_ADDRESS);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

BOOL CChatClientLobbyDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: Add your specialized code here and/or call the base class
	
	Packet *packet = NULL;
	while (packet = GetChatClientDoc().Receive())
	{

		switch (RakNet::GetPacketIdentifier(packet))
		{
		case ID_REMOTE_DISCONNECTION_NOTIFICATION:
			GetLogView().WriteLog(_T("Another client has disconnected."));			
			break;
		case ID_REMOTE_CONNECTION_LOST:
			GetLogView().WriteLog(_T("Another client has lost the connection."));
			break;
		case ID_REMOTE_NEW_INCOMING_CONNECTION:
			GetLogView().WriteLog(_T("Another client has connected."));
			break;
		case ID_CONNECTION_REQUEST_ACCEPTED:
			{
				GetLogView().WriteLog(_T("Our connection request has been accepted."));
				QueryChatRoom();

			}
			break;
		case ID_NEW_INCOMING_CONNECTION:
			GetLogView().WriteLog(_T("A connection is incoming."));
			break;
		case ID_NO_FREE_INCOMING_CONNECTIONS:
			GetLogView().WriteLog(_T("The server is full."));
			break;
		case ID_DISCONNECTION_NOTIFICATION:
			GetLogView().WriteLog(_T("A client has disconnected."));
			break;
		case ID_CONNECTION_LOST:
			GetLogView().WriteLog(_T("A client lost the connection."));
			break;
		case ID_CREATE_CHATROOM_ACK:
			{
				
				CString strRoomName;
				CreateChatRoomAck createChatRoomAck;
				RakNet::BitStream bitStream(packet->data, packet->length, false);
				bitStream.IgnoreBytes(sizeof(MessageID));
				bitStream.Read(createChatRoomAck.m_bSuccess);
				bitStream.Read(createChatRoomAck.m_chatRoomID);
				RakNet::ReadStringFromBitStream(bitStream, strRoomName);

				insertChatRoom(createChatRoomAck.m_chatRoomID, strRoomName);				
			}
			break;
		case ID_JOIN_CHATROOM_ACK:
			{
				JoinChatRoomAck joinChatRoomAck;
				RakNet::BitStream bitStream(packet->data, packet->length, false);
				bitStream.IgnoreBytes(sizeof(MessageID));

				bitStream.Read(joinChatRoomAck.m_bSuccess);
				if (joinChatRoomAck.m_bSuccess == true)
				{
					CChatRoomClientDlg* pChatClientDlg = new CChatRoomClientDlg;
					pChatClientDlg->SetChatClientDoc(GetChatClientDoc());
					pChatClientDlg->SetLogView(GetLogView());
					pChatClientDlg->SetServerAddress(packet->systemAddress);
					{
						UpdateData(TRUE);

						BYTE ipByte[4];
						m_coordinatorAddress.GetAddress(ipByte[0], ipByte[1], ipByte[2], ipByte[3]);

						CStringA strAddress;
						strAddress.Format(("%d.%d.%d.%d"), ipByte[0], ipByte[1], ipByte[2], ipByte[3]);
						
						pChatClientDlg->SetCoordinatorAddress(SystemAddress(strAddress.GetBuffer(), m_coordinatorPort));

					}
					
					pChatClientDlg->Create(CChatRoomClientDlg::IDD, GetParent());					
					GetChatClientDoc().SwitchDlg(*this, *pChatClientDlg);

					bitStream.Read(joinChatRoomAck.m_userCount);
					for(BYTE i = 0; i < joinChatRoomAck.m_userCount; ++i)
					{
						RakNetGUID userGuid;
						bitStream.Read(userGuid);
						pChatClientDlg->JoinRoom(userGuid);
					}
					GetChatClientDoc().DeallocatePacket(packet);
					CChatClientBaseDlg::PreTranslateMessage(pMsg);

					delete this;
					return true;
				}
				else
				{

				}
			}
			break;
		case ID_QUERY_CHATROOM_ACK:
			{
				QueryChatRoomAck queryChatRoomAck;
				RakNet::BitStream bitStream(packet->data, packet->length, false);
				bitStream.IgnoreBytes(sizeof(MessageID));
				bitStream.Read(queryChatRoomAck.m_roomCount);
				for(BYTE i = 0; i < queryChatRoomAck.m_roomCount; ++i)
				{
					NetworkID roomID;
					CString strRoomName;
					bitStream.Read(roomID);
					RakNet::ReadStringFromBitStream(bitStream, strRoomName);

					insertChatRoom(roomID, strRoomName);
				}
			}
			break;
		default:
			{
				CString strChat;
				strChat.Format(_T("Message with identifier %i has arrived."), packet->data[0]);
				GetLogView().WriteLog(strChat.GetBuffer());
			}
			break;
		}

		GetChatClientDoc().DeallocatePacket(packet);
	}
	return CChatClientBaseDlg::PreTranslateMessage(pMsg);
}

void CChatClientLobbyDlg::OnBnClickedButtonCreateRoom()
{
	// TODO: Add your control notification handler code here
	CString roomName;
	CInputBox inputBox(this);	
	if (IDOK == inputBox.Show(_T("Room name"), roomName))
	{
		if (0 == roomName.GetLength())
		{
			return;
		}
		
		RakNet::BitStream bitStream;
		bitStream.Write(CreateChatRoomReq().GetMessageID());
		RakNet::WriteStringToBitStream(bitStream, roomName);
		GetChatClientDoc().Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);	
	}
}

void CChatClientLobbyDlg::OnBnClickedButtonJoinRoom()
{
	// TODO: Add your control notification handler code here
	int item = m_lobby.GetSelectionMark();
	if (item == -1)
	{
		return;
	}

	NetworkID* pRoomID = reinterpret_cast<NetworkID*>(m_lobby.GetItemData(item));
	RakNet::BitStream bitStream;
	bitStream.Write(JoinChatRoomReq().GetMessageID());
	bitStream.Write(*pRoomID);
	GetChatClientDoc().Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);	

}

void CChatClientLobbyDlg::insertChatRoom( NetworkID& roomID, const TCHAR* pRoomName )
{
	NetworkID* pNetworkID = new NetworkID;
	*pNetworkID = roomID;

	CString strRoomID;
	strRoomID.Format(_T("%I64u"), roomID);

	int item = m_lobby.InsertItem(m_lobby.GetItemCount(), strRoomID);
	m_lobby.SetItemData(item, reinterpret_cast<DWORD_PTR>(pNetworkID));
	m_lobby.SetItem(item, 1, LVIF_TEXT, pRoomName, 0, 0, 0, 0);
}

void CChatClientLobbyDlg::QueryChatRoom()
{
	RakNet::BitStream bitStream;
	bitStream.Write(QueryChatRoomReq().GetMessageID());
	GetChatClientDoc().Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);	
}

